home *** CD-ROM | disk | FTP | other *** search
- /* @(#) proclist -- dispatch listserv requests to catmail
- *
- * Due to a bug in SCO Unix's MMDF, we can't use listserv's
- * /usr/server/catmail program within an aliased pipe. For
- * some odd reason, MMDF strips the first internet header line
- * in pipes. Listserv absolutely requires that this
- * "From address Date" header line be present.
- *
- * The work-around is to force incoming mail for listserv and
- * mailing lists to land in physical mailboxes belonging to
- * pseudo-users. This will require creating /etc/passwd users
- * to receive requests for the listserver and each mailing list.
- * The names are insignificant and may be aliased in
- * /usr/mmdf/table/alias.list. You will need one for 'listserv'
- * and one for each supported mailing list.
- *
- * This program, intended to be run either as a crontab entry or
- * interactively, will look for mail for the selected user and,
- * if the mail file exists, will strip the MMDF Ctrl-A separators
- * (which confuse listserv) from each message and pipe them through
- * /usr/server/catmail using the arguments specified on the command
- * line. See the server.nr dox for more information about catmail
- * arguments.
- *
- * Finally, we will launch the server program to process incoming
- * mail. The 'serverd' field in /usr/server/config file must
- * specify '-1' to tell the server not to load itself into the
- * background. The server will only run if we have found mail and
- * successfully piped it through catmail.
- *
- * Usage: proclist <user> <catmail_args>
- * i.e.: proclist listserv -r -f
- * proclist mcycle -L MCYCLE -f
- *
- * Author: Steve Manes manes@magpie.nycenet.edu
- *
- * Manes and Associates, NYC
- * July 1, 1992
- *
- * Developed for Learning Link, Linknet, Inc.
- * Public Broadcasting System, NYC
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <varargs.h>
- #include <time.h>
-
- #define SPOOLDIR "/usr/spool/mail"
- #define CATMAIL "/usr/server/catmail"
- #define SERVER "/usr/server/start"
- #define LOGFILE "/usr/spool/listserv/errlog"
- #define CTRL_A 1
- #define FILENAMESIZE 128
- #define RECBUFSIZE 512
- #define MAXRETRIES 10
- #define ERROR -1
-
- void usage();
- void log();
-
- void main( int argc, char *argv[] )
- {
- FILE *ofd, *catfd;
- int ifd, i, sz, count;
- struct stat Stat;
- struct flock Flock;
- int try;
-
- char buf[RECBUFSIZE+1],
- mailfile[FILENAMESIZE+1],
- workfile[FILENAMESIZE+1],
- catfile[FILENAMESIZE+1];
-
- if (argc < 2)
- usage();
-
- /* make sure that we have read/write access to
- * the user's mailfile */
- sprintf(mailfile, "%s/%s", SPOOLDIR, argv[1]);
- if (access(mailfile, F_OK)) {
- log("Mailfile %s not found!\n", mailfile);
- exit(1);
- }
- else if (access(mailfile, R_OK)) {
- log("Mailfile %s: no read permission!\n", mailfile);
- exit(1);
- }
- else if (access(mailfile, W_OK)) {
- log("Mailfile %s: no write permission!\n", mailfile);
- exit(1);
- }
- else if (stat(mailfile, &Stat)) {
- log("Can't stat %s!\n", mailfile);
- exit(1);
- }
- else if (Stat.st_size < 1) {
- log("%s has no mail for me\n", mailfile);
- exit(1);
- }
-
- /* make sure we can open a pipe to listserv's catmail */
- strcpy(catfile, CATMAIL);
- if (access(catfile, X_OK)) {
- log("Can't execute %s\n", catfile);
- exit( 1 );
- }
- for (i=2; i < argc; i++) { /* append catmail's command line */
- strcat(catfile, " ");
- strcat(catfile, argv[i]);
- }
-
- /* open the mailfile */
- if ((ifd = open(mailfile, O_RDWR)) == ERROR) {
- log("Can't open input %s\n", mailfile);
- exit(1);
- }
-
- /* lock the mailfile from other processes */
- Flock.l_type = F_WRLCK; /* write-lock only */
- Flock.l_whence = 0L; /* from beginning of file */
- Flock.l_start = Flock.l_len = 0L; /* till the end of file */
-
- /* wait twenty seconds to assert a lock */
- for (try=0; fcntl(ifd, F_SETLK, &Flock) < 0; try++) {
- if (try == MAXRETRIES) {
- log("Can't lock %s\n", mailfile);
- exit(1);
- }
- sleep(2); /* wait a coupla seconds... */
- }
-
- /* copy mail file to tmp directory for processing */
- sprintf(workfile, "/tmp/PROCLIST.%d", getpid());
- if ((ofd = fopen(workfile, "w+")) == NULL) {
- log("Can't open output %s\n", workfile);
- exit(1);
- }
- while( (sz = read(ifd, buf, RECBUFSIZE)) > 0)
- fwrite(buf, sizeof(char), sz, ofd);
-
- chsize(ifd, 0L); /* make file empty */
-
- /* unlock the file */
- Flock.l_type = F_UNLCK;
- Flock.l_whence = 0L; /* from beginning of file */
- Flock.l_start = Flock.l_len = 0L; /* till the end of file */
- fcntl(ifd, F_SETLK, &Flock);
- close(ifd); /* and close it */
-
- /* At this point, we have the user's mailfile copied to /tmp,
- * where we can operate on it without being disturbed by other
- * processes. We also zapped his SPOOLDIR mail so it's ready
- * to accept mail without us getting in the way. */
-
- rewind(ofd); /* back to the top */
- catfd = NULL;
- count = 0;
-
- /* page through the mail file, piping each message to catmail */
- while (fgets(buf, RECBUFSIZE, ofd) != NULL) {
-
- /* MMDF's message separators make this easy, but
- * listserv will choke on 'em so stifle 'em */
- if (buf[0] == CTRL_A) {
- if (catfd != NULL) {
- pclose(catfd);
- catfd = NULL;
- }
- continue;
- }
- if (catfd == NULL) {
- if ((catfd = popen(catfile, "w")) == NULL) {
- log("Can't open pipe to %s\n", buf);
- exit( 1 );
- }
- count++;
- }
- fputs(buf, catfd);
- }
-
- if (catfd != NULL)
- pclose(catfd); /* close the CATMAIL pipe */
- fclose(ofd); /* close the /tmp workfile... */
- unlink(workfile); /* and delete it. */
-
- log("%d message(s) processed\n", count);
- if (execl(SERVER, "start", "-c", NULL) == ERROR)
- perror(SERVER);
- }
-
- /*---[ usage ]-------------------------------------------------------------
- show program arguments
- --------------------------------------------------------------------------*/
- void usage()
- {
- fprintf(stderr, "usage: proclist <user> <catmail arguments>\n");
- exit( 1 );
- }
-
- /*---[ log ]---------------------------------------------------------------
- log error messages to file LOGFILE
- if LOGFILE, doesn't exist, don't create it
- --------------------------------------------------------------------------*/
- void log( va_alist )
- va_dcl
- {
- va_list args;
- char *fmt, tbuf[20];
- FILE *fd;
- time_t t;
-
- if ( !access(LOGFILE, W_OK) ) { /* is there a logfile? */
- va_start(args);
- fmt = va_arg(args, char *);
- time(&t);
- if ((fd = fopen(LOGFILE, "a")) != NULL) {
- strftime(tbuf, 20, "%m/%d %H:%M:%S ", localtime(&t));
- fprintf(fd, "%s", tbuf);
- vfprintf(fd, fmt, args);
- va_end(args);
- fclose(fd);
- }
- }
- }
-
- /* END PROCLIST */
-